package com.lagou.nettyspringboot.netty;

import com.lagou.nettyspringboot.config.NettyConfig;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;

/**
 * @description: nettyWebSocket服务端
 * @author: yx
 * @date: 2021/11/16 10:31
 */
@Component
public class NettyWebSocketServer implements Runnable {

    @Autowired
    private NettyConfig nettyConfig;

    @Autowired
    private WebSocketChannelInit webSocketChannelInit;

    //创建bossGroup线程组: 处理网络事件--连接事件,不设置线程数默认为: 2*处理器线程数
    private NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);

    //创建workerGroup线程组: 处理网络事件--读写事件,不设置线程数默认为: 2*处理器线程数
    private NioEventLoopGroup workerGroup = new NioEventLoopGroup();

    //资源关闭-容器销毁时执行
    @PreDestroy
    private void close() {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }

    @Override
    public void run() {
        try {
            //1. 创建服务端启动助手
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            //2. 设置bossGroup线程组和workerGroup线程组
            serverBootstrap.group(bossGroup, workerGroup);
            //3.设置参数
            serverBootstrap.channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.DEBUG))//设置日志处理器,将日志的等级设置为debug
                    .childHandler(webSocketChannelInit);//设置通道初始化对象
            //4. 启动服务端并绑定端口,同时将异步改为同步
            ChannelFuture future = serverBootstrap.bind(nettyConfig.getPort()).sync();
            System.out.println("=========nettyWebSocket服务端启动成功=========");
            //5. 关闭通道(并不是真正的关闭,而是一直监听通道关闭状态)和关闭连接池
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }
}
